package info.sybian.util;

import info.sybian.model.User;
import info.sybian.service.Do;
import info.sybian.service.Do.Service;

import java.util.HashMap;

import objot.codec.Codec;
import objot.container.Bind;
import objot.container.Container;
import objot.container.Factory;
import objot.container.Inject;
import objot.util.Class2;
import objot.util.Mod2;

import com.sleepycat.je.DatabaseConfig;
import com.sleepycat.je.Environment;

public class Services {
	public static Container build(final Environment env, final DatabaseConfig dc) throws Exception {
		// final Weaver w = new Weaver() {
		// @Override
		// protected Object forWeave(Class<? extends Aspect> ac, Method m) throws Exception {
		// return this;
		// }
		// };

		final Codec codec = new Codec() {
			String modelPrefix = Class2.packageName(User.class).concat(".");

			@Override
			protected Object byName(String name, Object ruleKey) throws Exception {
				if(name.length() == 0)
					return HashMap.class;
				return Class.forName(modelPrefix.concat(name));
			}

			@Override
			protected String name(Object o, Class<?> c, Object ruleKey) throws Exception {
				if(o instanceof HashMap<?, ?>)
					return "";
				return Class2.selfName(c);
			}
		};

		Factory sessionFactory = new Factory() {
			{
				bind(Environment.class);
				bind(DatabaseConfig.class);
				bind(Codec.class);
			}

			@Override
			protected Object forBind(Class<?> c, Bind b) throws Exception {
				return c == Environment.class ? b.obj(env) : c == DatabaseConfig.class ? b.obj(dc)
						: c == Codec.class ? b.obj(codec) : b;
			}
		};
		final Container session = sessionFactory.create(null);

		Factory requestFactory = new Factory() {
			{
				for(Class<?> c : Class2.packageClasses(Do.class))
					if(Mod2.match(c, Mod2.PUBLIC, Mod2.ABSTRACT) && c.isAnnotationPresent(Service.class))
						bind(c);
			}

			@Override
			protected Object forBind(Class<?> c, Bind b) throws Exception {
				if(session.bound(c))
					return b.mode(Inject.Parent.class);
				return c.isSynthetic() ? b : b.cla(c);
			}
		};
		Container request = requestFactory.create(session);
		return request;
	}
}
